# coding=utf-8
import torch

w = torch.tensor([1.], requires_grad=True)
x = torch.tensor([2.], requires_grad=True)

a = torch.add(w,x)
a.retain_grad()   #  保留非叶子节点的的梯度
b = torch.add(w,1)
y = torch.mul(a,b)

y.backward()
print(w.grad)

print("is_leaf:\n", w.is_leaf, x.is_leaf, a.is_leaf, b.is_leaf, y.is_leaf)

print("gradient:\n", w.grad, x.grad, a.grad, b.grad, y.grad)

# torch.Tensor中还有一个属性为grad_fn，grad_fn的作用是记录创建该张量时所用的方法（函数），该属性在梯度反向传播的时候用到。例如在上面提到的例子中，y.grad_fn = ，y在反向传播的时候会记录y是用乘法得到的，所用在求解a和b的梯度的时候就会用到乘法的求导法则去求解a和b的梯度。同样，对于a有a.grad_fn=，对于b有b.grad_fn=，由于a和b是通过加法得到的，所以grad_fn都是AddBackword0。可以通过代码观看各个变量的属性。

print("grad_fn:\n", w.grad_fn, x.grad_fn, a.grad_fn, b.grad_fn, y.grad_fn)